function Matrix () {
	var data = new HashMap ();
	this.setAction = function (source, target, action) {
		var map = data.get (source);
		if (!map) {
			map = new HashMap ();
			data.put (source, map);
		}
		if (action == -1) { // remove action
			map.remove (target);
			if (map.isEmpty ()) data.remove (source);
		} else
			map.put (target, action);
	}
	
	this.getAction = function (source, target) {
		var list = data.get (source);
		if (list) return list.get (target);
		return null;
	}
	
	this.toString = function () {
		var s = "";
		var keys = data.keySet ();
		var values = data.values ();
		for (var i = 0; i < keys.length; i ++) {
			if (i > 0) s += "|";
			var key = keys [i];
			var map = values [i];
			if (!map.isEmpty ()) {
				s += key + ":{";
				var vs = map.values ();
				for (var j = 0; j < vs.length; j ++) {
					if (j > 0) s += ",";
					s += vs [j];
				}
				s += "}";
			}
		}
		return s;
	}
	
	this.toXMLString = function () {
		var s = "<?xml version = '1.0' encoding = 'utf-8'?><matrix>";
		var keys = data.keySet ();
		var values = data.values ();
		for (var i = 0; i < keys.length; i ++) {
			var key = keys [i];
			var map = values [i];
			if (!map.isEmpty ()) {
				var vs = map.values ();
				for (var j = 0; j < vs.length; j ++)
					s += "<item source-state='" + key + "' action='" + vs [j] + "'/>";
			}
		}
		s += "</matrix>";
		return s;
	}
}

var __Matrixes = [];